#include "instructions/control/return.h"

namespace jvm {
    namespace instructions {

        void RETURN::execute(std::shared_ptr<rtda::Frame> frame) {
            frame->getThread()->popFrame();
        }

        void ARETURN::execute(std::shared_ptr<rtda::Frame> frame) {
            auto thread = frame->getThread();
            auto currentFrame = thread->popFrame();
            auto invokerFrame = thread->topFrame();
            auto ref = currentFrame->getOperandStack()->popRef();
            invokerFrame->getOperandStack()->pushRef(ref);
        }

        void DRETURN::execute(std::shared_ptr<rtda::Frame> frame) {
            auto thread = frame->getThread();
            auto currentFrame = thread->popFrame();
            auto invokerFrame = thread->topFrame();
            auto val = currentFrame->getOperandStack()->popDouble();
            invokerFrame->getOperandStack()->pushDouble(val);
        }

        void FRETURN::execute(std::shared_ptr<rtda::Frame> frame) {
            auto thread = frame->getThread();
            auto currentFrame = thread->popFrame();
            auto invokerFrame = thread->topFrame();
            auto val = currentFrame->getOperandStack()->popFloat();
            invokerFrame->getOperandStack()->pushFloat(val);
        }

 
        void IRETURN::execute(std::shared_ptr<rtda::Frame> frame) {
            auto thread = frame->getThread();
            auto currentFrame = thread->popFrame();
            auto invokerFrame = thread->topFrame();
            auto val = currentFrame->getOperandStack()->popInt();
            invokerFrame->getOperandStack()->pushInt(val);
        }

        void LRETURN::execute(std::shared_ptr<rtda::Frame> frame) {
            auto thread = frame->getThread();
            auto currentFrame = thread->popFrame();
            auto invokerFrame = thread->topFrame();
            auto val = currentFrame->getOperandStack()->popLong();
            invokerFrame->getOperandStack()->pushLong(val);
        }

    } // namespace instructions
} // namespace jvm